import { Object3D, WebGLRenderer } from "three";
import MeshUtil from "../../renderExtension/utils/MeshUtil";
import { BaseTileMap } from "../../map/BaseTileMap";
import { App } from "../../application";
import Const from "../../application/constants/Const";
import BaseTile from "../../map/Tile/BaseTile";
import { SwitchEvent } from "./TileSwitchController";

/**
 * 层级往下滚动的时候，对瓦片加载的控制
 */
class TileSwitcher {
    private oldTile;
    private newTileNumList: Array<{x: number, y: number, z: number}>; //要加载的新瓦片的编号
    private tileRange: { minCol: number, maxCol: number, minRow: number, maxRow: number, zoom: number };
    private baseTileMap: BaseTileMap;
    private loadedCount: number;
    private children;
    private extraOldTileArray: Array<Object3D>;
    private isSwitch = true;
    private switchEvent: SwitchEvent;

    /**
     * 层级切换时的瓦片加载
     * @param oldTile 旧的瓦片
     * @param newTileNumList 旧瓦片要加载的子瓦片或者父瓦片的编号，这些瓦片加载成功后，会替换oldTile
     * @param tileRange 当前相机可视区域内要加载瓦片的编号,用来剔除newTileNumList中不在可视区域的瓦片
     */
    public constructor(baseTileMap: BaseTileMap, oldTile, newTileNumList, tileRange){
        this.oldTile = oldTile;
        this.newTileNumList = newTileNumList;
        this.tileRange = tileRange;
        this.baseTileMap = baseTileMap;
        this.loadedCount = 0;
        this.children = new Array();
        this.extraOldTileArray = [];
    }

    public setSwitchEvent(switchEvent){
        this.switchEvent = switchEvent;
    }

    public switch(tileList: Array<string>){//当newTileNumList的瓦片都加载成功的时候，把oldTile瓦片删除
        if(this.children == null){
            return;
        }

        let self = this;

        this.newTileNumList.forEach(tile => {
            if(tile.z == self.tileRange.zoom){
                if(tile.x < self.tileRange.minCol){
                    return;
                }else if(tile.x > self.tileRange.maxCol){
                    return;
                }else if(tile.y < self.tileRange.minRow){
                    return;
                }else if(tile.y > self.tileRange.maxRow){
                    return;
                }
                let tileModel = self.baseTileMap.loadTile(tile, self.loadCallback.bind(self));
                if(!tileModel || !self.children){
                    return;
                }

                let tileJson = JSON.stringify(tile);
                tileList.push(tileJson);
                
                if(this.baseTileMap.tileType != 'shape'){ //只有非shape瓦片时，才把新瓦片的渲染顺序往后放
                    // tileModel.renderOrder = Const.RenderOrder.Map + 1;
                    tileModel.renderOrder = self.baseTileMap.mapOrder + 1;
                }
                tileModel.updateVisibility();

                tileModel.needsUpdate = true; 
                self.children.push(tileModel);
            }
        });
        
        if(this.children && this.children.length == 0){ //没有子瓦片要加载
            this.isSwitch = false;
        }
        return this.isSwitch;
    }

    public isCanSwitch(){
        return this.isSwitch;
    }

    public addExtraOldTile(extraTile){
        this.extraOldTileArray.push(extraTile as never);
    }

    private loadCallback(tileModel?){
        if(tileModel){
            // tileModel.renderOrder = Const.RenderOrder.Map;
            tileModel.cancleNetTask();
            tileModel.restoreVisibility();    
        }
       
        this.loadedCount++;
        
        if(!this.children){
            return;
        }

        if(this.loadedCount >= this.children.length){ //所有需要加载的瓦片已经加载成功
            this.oldTile.dispose();
            this.baseTileMap.remove(this.oldTile);
            
            if(this.baseTileMap.tileType != 'shape'){
                for(let i=0; i<this.children.length; i++){
                    let curModel = this.children[i];
                    curModel.renderOrder = this.baseTileMap.mapOrder;
                }
            }

            let self = this;
            this.extraOldTileArray.forEach(element => {
                element['dispose']();
                self.baseTileMap.remove(element);
            });

            if(this.switchEvent){
                this.switchEvent.event(this);
            }
            this.children = null;
        }
    }

    public cancle(){
        if(!this.children){
            return;
        }

        let self = this;
        this.children.forEach(element => {
            self.loadCallback(element);
        });
        
    }
}
export { TileSwitcher }